﻿using System;
using System.Collections.Generic;
using System.Linq;
using CLM.Gestao.Interfaces;
using CLM.Gestao.Administrador.DAL;

namespace CLM.Gestao.Administrador.BLL
{
    public class Usuario : UsuarioBLO<TB_USUARIO>
    {
        #region Propriedades

        public int IdUsuario { get; set; }
        public string NomeUsuario { get; set; }
        public string LoginUsuario { get; set; }
        public bool IndicaAtivo { get; set; }
        public PerfilAcesso PerfilAcesso { get; set; }

        #endregion Propriedades

        #region Conversões

        private List<TB_USUARIO> ConvertToEDM(List<Lista> pLista)
        {
            List<TB_USUARIO> List = (from l in pLista
                                     select new TB_USUARIO
                                     {
                                         ID_USUARIO = l.IdUsuario,
                                         NOME_USUARIO = l.NomeUsuario,
                                         LOGIN_USUARIO = l.LoginUsuario,
                                         DATA_INCLUSAO = DateTime.Now,
                                         ID_PERFIL_ACESSO = l.IdPerfilAcesso
                                     }).ToList();
            return List;
        }

        private List<Lista> ConvertToContext(IQueryable<TB_USUARIO> pContext)
        {
            List<Lista> List = (from l in pContext
                                select new Lista
                                {
                                    IdUsuario = l.ID_USUARIO,
                                    NomeUsuario = l.NOME_USUARIO,
                                    LoginUsuario = l.LOGIN_USUARIO,
                                    IdPerfilAcesso = l.TB_PERFIL_ACESSO.ID_PERFIL_ACESSO,
                                    NomePerfilAcesso = l.TB_PERFIL_ACESSO.NOME_PERFIL_ACESSO
                                }).ToList();
            return List;
        }

        #endregion Conversões

        #region CRUD

        /// <summary>
        /// Adiciona
        /// </summary>
        /// <param name="pLista">pLista</param>
        public void Add(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Add(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Deleta
        /// </summary>
        /// <param name="pLista">pLista</param>
        public void Delete(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Delete(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        
        /// <summary>
        /// Atualiza
        /// </summary>
        /// <param name="pLista">pLista</param>
        public void Update(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Update(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Efetua a pesquisa na tabela, filtrando as solicitações do usuário
        /// </summary>
        /// <param name="pPesquisa">pPesquisa</param>
        /// <returns>Lista</returns>
        private IQueryable<TB_USUARIO> Get(Lista pPesquisa)
        {
            IQueryable<TB_USUARIO> Consulta;

            Consulta = from p in GetAll()
                       select p;
            if (pPesquisa != null)
            {
                if (!string.IsNullOrWhiteSpace(pPesquisa.NomeUsuario))
                    Consulta = from p in Consulta where p.NOME_USUARIO.Contains(pPesquisa.NomeUsuario) select p;

                if (!string.IsNullOrWhiteSpace(pPesquisa.LoginUsuario))
                    Consulta = from p in Consulta where p.LOGIN_USUARIO.Contains(pPesquisa.LoginUsuario) select p;

                if (pPesquisa.IdPerfilAcesso > 0)
                    Consulta = from p in Consulta where p.TB_PERFIL_ACESSO.ID_PERFIL_ACESSO == pPesquisa.IdPerfilAcesso select p;
            }
            return Consulta;
        }

        #endregion CRUD

        #region Retorna Listas e Itens

        public List<Lista> GetLista()
        {
            return GetLista(new Lista());
        }

        public List<Lista> GetLista(Lista pPesquisa)
        {
            //var ListaUsuario = (from p in Get(pPesquisa)
            //                    select new Lista()
            //                    {
            //                        IdUsuario = p.ID_USUARIO,
            //                        NomeUsuario = p.NOME_USUARIO,
            //                        LoginUsuario = p.LOGIN_USUARIO,
            //                        IdPerfilAcesso = p.TB_PERFIL_ACESSO.ID_PERFIL_ACESSO,
            //                        NomePerfilAcesso = p.TB_PERFIL_ACESSO.NOME_PERFIL_ACESSO
            //                    }).ToList();

            var ListaUsuario = ConvertToContext(Get(pPesquisa));
            return ListaUsuario;
        }

        public List<Itens> GetItens()
        {
            return GetItens(new Lista());
        }

        public List<Itens> GetItens(Lista pPesquisa)
        {
            List<Itens> ListaUsuario = (from p in Get(pPesquisa)
                                        select new Itens()
                                        {
                                            IdUsuario = p.ID_USUARIO,
                                            NomeUsuario = p.NOME_USUARIO
                                        }).ToList();
            return ListaUsuario;
        }

        #endregion Retorna Listas e Itens

        #region Consultas

        public Usuario Login(string pWindowsUser)
        {
            Usuario UsuarioLogado;
            try
            {
                var Verifica = from p in GetAll()
                               select p;

                Verifica = from p in GetAll()
                           where p.LOGIN_USUARIO == pWindowsUser
                           select p;

                if (Verifica != null && Verifica.Count() > 0)
                {
                    UsuarioLogado = (from p in Verifica
                                     select new Usuario()
                                     {
                                         IdUsuario = p.ID_USUARIO,
                                         NomeUsuario = p.NOME_USUARIO,
                                         LoginUsuario = p.LOGIN_USUARIO,
                                         PerfilAcesso = new BLL.PerfilAcesso
                                         {
                                             IdPerfilAcesso = p.TB_PERFIL_ACESSO.ID_PERFIL_ACESSO,
                                             NomePerfilAcesso = p.TB_PERFIL_ACESSO.NOME_PERFIL_ACESSO,
                                             AlocacaoDespesas = p.TB_PERFIL_ACESSO.ABRE_CADASTROS,
                                             CalcularRateioProduto = p.TB_PERFIL_ACESSO.ABRE_CONCILIACAO,
                                             ExportarCustosDespesas = p.TB_PERFIL_ACESSO.ABRE_CONTROLADORIA,
                                             ExportarVendas = p.TB_PERFIL_ACESSO.ABRE_JUSTIFICATIVA,
                                             ImportacaoCusto = p.TB_PERFIL_ACESSO.ABRE_PAINEL,
                                             ImportacaoProdutoGlobal = p.TB_PERFIL_ACESSO.ABRE_PERFIL_ACESSO,
                                             ImportacaoProvisoesDevolucao = p.TB_PERFIL_ACESSO.ABRE_SUMARIO_EXECUTIVO,
                                             ImportaCustoUnitarioAmostra = p.TB_PERFIL_ACESSO.ABRE_SUMARIO_FOPAG,
                                             ImportaCustoUnitarioProduto = p.TB_PERFIL_ACESSO.ABRE_SUMARIO_PROJETO,
                                             ImportarPromocaoGrade = p.TB_PERFIL_ACESSO.DIFERE_ORCAMENTO,
                                             ImportarRateioGGF = p.TB_PERFIL_ACESSO.EDITA_WORKFLOW,
                                             ManutencaoCentroCusto = p.TB_PERFIL_ACESSO.EFETUA_CALCULOS,
                                             ManutencaoContaContabil = p.TB_PERFIL_ACESSO.FOPAG_NO_SUM_COMPLETO,
                                             ManutencaoPerfilAcesso = p.TB_PERFIL_ACESSO.GERA_BSC,
                                             ManutencaoPeriodo = p.TB_PERFIL_ACESSO.HISTORICO_PROJETOS,
                                             ManutencaoProdutos = p.TB_PERFIL_ACESSO.IMPORTA_ARQUIVOS,
                                             ManutencaoUsuario = p.TB_PERFIL_ACESSO.IMPORTA_CENTROCUSTO,
                                             PremissasCalculoCusto = p.TB_PERFIL_ACESSO.IMPORTA_DESPESAS_COMPROMETIDAS,
                                             RelatorioDivergenciaProdutos = p.TB_PERFIL_ACESSO.IMPORTA_HISTORICO,
                                             RelatorioIndicadoresDespesas = p.TB_PERFIL_ACESSO.IMPORTA_LANCAMENTOS,
                                             RelatorioIndicadoresVenda = p.TB_PERFIL_ACESSO.IMPORTA_ORCAMENTO,
                                             SincronizaCentroCusto = p.TB_PERFIL_ACESSO.IMPORTA_PERIODO_FECHADO,
                                             SincronizaContaContabil = p.TB_PERFIL_ACESSO.IMPORTA_PRODUTO,
                                             SincronizaProdutos = p.TB_PERFIL_ACESSO.INDICA_ACESSA_SISTEMA,
                                             SincronizarDespesasRealizadas = p.TB_PERFIL_ACESSO.INDICA_APROVACAO_ORCAMENTO,
                                             SincronizaVendaRealizada = p.TB_PERFIL_ACESSO.INDICA_APROVACAO_QUADRO_FUNCIONARIO,
                                             VisualizarPNL = p.TB_PERFIL_ACESSO.INDICA_IMPORTACAO_FUNCIONARIOS
                                         }
                                     }).ToList().First();

                }
                else
                {
                    throw new Exception("Usuário não cadastrado no sistema");
                }
                return UsuarioLogado;
            }
            catch (Exception Ex)
            {
                throw new Exception(Ex.Message);
            }
        }

        #endregion Consultas

        #region Classes

        /// <summary>
        /// Preenche o combobox
        /// </summary>
        public class Itens
        {
            public int IdUsuario { get; set; }
            public string NomeUsuario { get; set; }
        }

        /// <summary>
        /// Lista com as propriedades da classe
        /// </summary>
        public class Lista
        {
            public int IdUsuario { get; set; }
            public string NomeUsuario { get; set; }
            public string LoginUsuario { get; set; }
            public int IdPerfilAcesso { get; set; }
            public string NomePerfilAcesso { get; set; }
            public bool IndicaAtivo { get; set; }
        }

        #endregion Classes
    }

    public class UsuarioBLO<T> : IBLO<T> where T : TB_USUARIO
    {
        /// <summary>
        /// UsuarioDAO
        /// </summary>
        private UsuarioDAO<T> _base = new UsuarioDAO<T>();

        /// <summary>
        /// Adiciona uma entidade no sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public T Add(T pEntity)
        {
            Validate(pEntity);
            _base.Add(pEntity);
            return _base.Save(pEntity);
        }

        /// <summary>
        /// Salva uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public T Save(T pEntity)
        {
            Validate(pEntity);
            return _base.Save(pEntity);
        }

        /// <summary>
        /// Deleta uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        public void Delete(T pEntity)
        {
            _base.Delete(pEntity);
            _base.Save(pEntity);
        }

        /// <summary>
        /// Atualiza uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public T Update(T pEntity)
        {
            Validate(pEntity);
            _base.Update(pEntity);
            return _base.Save(pEntity);
        }

        /// <summary>
        /// Recupera uma entidade do sistema
        /// </summary>
        /// <returns>Lista</returns>
        public IQueryable<T> GetAll()
        {
            return _base.GetAll();
        }

        /// <summary>
        /// Valida a consistência da Entidade antes de 'comitar' a transação
        /// </summary>
        /// <param name="pEntity">Entidade</param>
        public void Validate(T pEntity)
        {
            int uservalidate = (from u in _base.GetAll()
                                where (u.LOGIN_USUARIO == pEntity.LOGIN_USUARIO && u.ID_USUARIO != pEntity.ID_USUARIO)
                                select u).Count();

            if (uservalidate > 0)
                throw new Exception("Já existe um usuário cadastrado com esse Login.");

            uservalidate = (from u in _base.GetAll()
                                where (u.NOME_USUARIO == pEntity.NOME_USUARIO && u.ID_USUARIO != pEntity.ID_USUARIO)
                                select u).Count();

            if (uservalidate > 0)
                throw new Exception("Já existe um usuário cadastrado com esse Nome.");

            ////Esta validação não é necessário no momento, pois não apresentamos o funcionario para selecao na interface.
            //uservalidate = (from u in _base.GetAll()
            //                where (u.ID_FUNCIONARIO != null && u.ID_FUNCIONARIO == pEntity.ID_FUNCIONARIO)
            //                select u).Count();

            //if (uservalidate > 0)
            //    throw new Exception("Já existe um usuário relacionado com esse Funcionário.");
        }
    }
}